#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

#define Up    1
#define Down  -1
#define Left  2
#define Right -2
int cmd;
int dir;
void initNncurse()
{
	initscr();
    	keypad(stdscr,1);
	noecho();	
}

struct Snake{
	int hang;
	int lie;
	struct Snake *next;
};

struct Snake *head=NULL;
struct Snake *tail=NULL;
struct Snake food;

int hasSnakeNode(int i,int j)
{
	struct Snake *p =head;
	while(p!=NULL)
	{
	   if(p->hang==i && p->lie ==j)
	     {
		return 1;
	     }
	   p=p->next;
	}
		return 0;
}

int hasFood(int i,int j)
{
	   if(food.hang==i && food.lie ==j)
	     {
		return 1;
	     }
		return 0;
}


void initPic()
{
	int Row;
	int Column;
 	move(0,0);	
	for(Row=0;Row<20;Row++)
	{
		if(Row==0)
		{
		    for(Column=0;Column<20;Column++)
			{
			  printw("--");
			}
			printw("\n");
		}//0 Row  
		if(Row>=0 &&Row<=19)
		{
		   for(Column=0;Column<=20;Column++)
		      {
			if(Column==0 ||Column==20)
			  {
			    printw("|");
			  }
			else if(hasSnakeNode(Row,Column))
				{ 
				  printw("[]");
				}
			else if(hasFood(Row,Column))
				{
				  printw("$$");
				}
			else
			  {
		            printw("  ");
			  }
		      }
		    printw("\n");
		}
		if(Row==19)
		{
		   for(Column=0;Column<20;Column++)
		      {
			printw("--");
		      }
		        printw("\nAuthor: Xwd\n");
		}
	}
}

void addNode()
{
	struct Snake *new=(struct Snake *)malloc(sizeof(struct Snake));
	new->next=NULL;
	switch(dir)
	{
	  case Up:
	   new->hang=tail->hang-1;
           new->lie=(tail->lie);
	   break;
	  case Down:
	   new->hang=tail->hang+1;
           new->lie=(tail->lie);
	   break;
	  case Left:
	   new->hang=tail->hang;
           new->lie=(tail->lie)-1;
	   break;
	  case Right:
	   new->hang=tail->hang;
           new->lie=(tail->lie)+1;
	   break;
	}
	tail->next=new;
	tail=new;
}

void initFood()
{	
   int x=rand()%20;
   int y=rand()%20;
  food.hang=x;
   food.lie=y;
}
void initSnake()
{ 
	initFood();	
	struct Snake *p;
	dir=Right;
	while(head!=NULL)
	{
	    p=head;
	    head=head->next;
	    free(p);
	}
	head=(struct Snake *)malloc(sizeof(struct Snake));
	head->hang=1;
	head->lie=1;
	head->next=NULL;

	tail=head;
	addNode();
	addNode();
	addNode();
}

void deleteNode()
{
     struct Snake *p=head;
     head=head->next;
     free(p);
}

int isDie()
{
    struct Snake *p=head;
    if(tail->lie==0 || tail->hang<0 ||tail->lie==20 ||tail->hang==20)
	{
		return 1;
	}	
     while(p->next!=NULL)
	{
	    if((p->hang==tail->hang) && (p->lie==tail->lie))
		{ 
			return 1;
		}  
	    p=p->next;
	    
	}
	return 0;
}
void moveSnake()
{
      addNode();
      if(hasFood(tail->hang,tail->lie))
	{
	initFood();
	}
	else
	{
      deleteNode();
	}
      if(isDie())
	{
	    initSnake();
	}
}

void *refresheFace()
{
        while(1){
        moveSnake();
        initPic();
        refresh();
        usleep(100000);
         }
}

void turn(int direction)//turn snake if Up and Down(Left and Right) putin no turn
{
	if(abs(direction)!=abs(dir))
	{
		dir=direction;
        }
}
void *changeDir()
{
	 while(1)
        {   
           cmd=getch();
           switch(cmd)
        {   
           case KEY_DOWN:
           turn(Down);
           break;

           case KEY_UP:
           turn(Up);
           break;

           case KEY_LEFT:
           turn(Left);
           break;

           case KEY_RIGHT:
           turn(Right);
           break;
        }   
          // printw("your input: %d\n",key);
        }
	
}
int main()
{	
	initNncurse();
	initSnake();
	initFood();
	initPic();
        pthread_t th1,th2;
	pthread_create(&th1,NULL,refresheFace,NULL);
	pthread_create(&th2,NULL,changeDir,NULL);
        while(1);
	
	getch();
	endwin();
	return 0;
}
